
<!doctype html>
<html lang="en" class="no-js">
  <head>
    
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width,initial-scale=1">
      
      
      
      <link rel="icon" href="../../../../static/images/favicon.png">
      <meta name="generator" content="mkdocs-1.3.0, mkdocs-material-8.2.8">
    
    
      
        <title>异地组网之 OpenVPN 快速部署 - WL4G DOCS</title>
      
    
    
      <link rel="stylesheet" href="../../../../assets/stylesheets/main.644de097.min.css">
      
        
        <link rel="stylesheet" href="../../../../assets/stylesheets/palette.e6a45f82.min.css">
        
      
    
    
    
      
        
        
        <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
        <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
        <style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
      
    
    
      <link rel="stylesheet" href="../../../../static/css/util.css">
    
    <script>__md_scope=new URL("../../../..",location),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
    
      

    
    
  </head>
  
  
    
    
      
    
    
    
    
    <body dir="ltr" data-md-color-scheme="default" data-md-color-primary="" data-md-color-accent="">
  
    
    
      <script>var palette=__md_get("__palette");if(palette&&"object"==typeof palette.color)for(var key of Object.keys(palette.color))document.body.setAttribute("data-md-color-"+key,palette.color[key])</script>
    
    <input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
    <input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
    <label class="md-overlay" for="__drawer"></label>
    <div data-md-component="skip">
      
        
        <a href="#openvpn" class="md-skip">
          Skip to content
        </a>
      
    </div>
    <div data-md-component="announce">
      
    </div>
    
      <div data-md-component="outdated" hidden>
        <aside class="md-banner md-banner--warning">
          
        </aside>
      </div>
    
    
      

<header class="md-header" data-md-component="header">
  <nav class="md-header__inner md-grid" aria-label="Header">
    <a href="../../../.." title="WL4G DOCS" class="md-header__button md-logo" aria-label="WL4G DOCS" data-md-component="logo">
      
  <img src="../../../../static/images/mylogo.jpeg" alt="logo">

    </a>
    <label class="md-header__button md-icon" for="__drawer">
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2z"/></svg>
    </label>
    <div class="md-header__title" data-md-component="header-title">
      <div class="md-header__ellipsis">
        <div class="md-header__topic">
          <span class="md-ellipsis">
            WL4G DOCS
          </span>
        </div>
        <div class="md-header__topic" data-md-component="header-topic">
          <span class="md-ellipsis">
            
              异地组网之 OpenVPN 快速部署
            
          </span>
        </div>
      </div>
    </div>
    
      <form class="md-header__option" data-md-component="palette">
        
          
          
          <input class="md-option" data-md-color-media="(prefers-color-scheme: light)" data-md-color-scheme="default" data-md-color-primary="" data-md-color-accent=""  aria-label="Switch to dark mode"  type="radio" name="__palette" id="__palette_1">
          
            <label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_2" hidden>
              <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M17 6H7c-3.31 0-6 2.69-6 6s2.69 6 6 6h10c3.31 0 6-2.69 6-6s-2.69-6-6-6zm0 10H7c-2.21 0-4-1.79-4-4s1.79-4 4-4h10c2.21 0 4 1.79 4 4s-1.79 4-4 4zM7 9c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/></svg>
            </label>
          
        
          
          
          <input class="md-option" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-scheme="slate" data-md-color-primary="" data-md-color-accent=""  aria-label="Switch to light mode"  type="radio" name="__palette" id="__palette_2">
          
            <label class="md-header__button md-icon" title="Switch to light mode" for="__palette_1" hidden>
              <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M17 7H7a5 5 0 0 0-5 5 5 5 0 0 0 5 5h10a5 5 0 0 0 5-5 5 5 0 0 0-5-5m0 8a3 3 0 0 1-3-3 3 3 0 0 1 3-3 3 3 0 0 1 3 3 3 3 0 0 1-3 3z"/></svg>
            </label>
          
        
      </form>
    
    
      <div class="md-header__option">
        <div class="md-select">
          
          <button class="md-header__button md-icon" aria-label="Select language">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="m12.87 15.07-2.54-2.51.03-.03A17.52 17.52 0 0 0 14.07 6H17V4h-7V2H8v2H1v2h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04M18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12m-2.62 7 1.62-4.33L19.12 17h-3.24z"/></svg>
          </button>
          <div class="md-select__inner">
            <ul class="md-select__list">
              
                <li class="md-select__item">
                  <a href="/en/" hreflang="en" class="md-select__link">
                    English
                  </a>
                </li>
                
                <li class="md-select__item">
                  <a href="/zh/" hreflang="zh" class="md-select__link">
                    简体中文
                  </a>
                </li>
                
            </ul>
          </div>
        </div>
      </div>
    
    
      <label class="md-header__button md-icon" for="__search">
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5z"/></svg>
      </label>
      <div class="md-search" data-md-component="search" role="dialog">
  <label class="md-search__overlay" for="__search"></label>
  <div class="md-search__inner" role="search">
    <form class="md-search__form" name="search">
      <input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
      <label class="md-search__icon md-icon" for="__search">
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5z"/></svg>
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12z"/></svg>
      </label>
      <nav class="md-search__options" aria-label="Search">
        
        <button type="reset" class="md-search__icon md-icon" aria-label="Clear" tabindex="-1">
          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"/></svg>
        </button>
      </nav>
      
        <div class="md-search__suggest" data-md-component="search-suggest"></div>
      
    </form>
    <div class="md-search__output">
      <div class="md-search__scrollwrap" data-md-scrollfix>
        <div class="md-search-result" data-md-component="search-result">
          <div class="md-search-result__meta">
            Initializing search
          </div>
          <ol class="md-search-result__list"></ol>
        </div>
      </div>
    </div>
  </div>
</div>
    
    
  </nav>
  
</header>
    
    <div class="md-container" data-md-component="container">
      
      
        
          
            
<nav class="md-tabs" aria-label="Tabs" data-md-component="tabs">
  <div class="md-tabs__inner md-grid">
    <ul class="md-tabs__list">
      
        
  
  


  
  
  
    <li class="md-tabs__item">
      <a href="../../../.." class="md-tabs__link">
        Getting Started
      </a>
    </li>
  

      
    </ul>
  </div>
</nav>
          
        
      
      <main class="md-main" data-md-component="main">
        <div class="md-main__inner md-grid">
          
            
              
              <div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
                <div class="md-sidebar__scrollwrap">
                  <div class="md-sidebar__inner">
                    

  


  

<nav class="md-nav md-nav--primary md-nav--lifted md-nav--integrated" aria-label="Navigation" data-md-level="0">
  <label class="md-nav__title" for="__drawer">
    <a href="../../../.." title="WL4G DOCS" class="md-nav__button md-logo" aria-label="WL4G DOCS" data-md-component="logo">
      
  <img src="../../../../static/images/mylogo.jpeg" alt="logo">

    </a>
    WL4G DOCS
  </label>
  
  <ul class="md-nav__list" data-md-scrollfix>
    
      
      
      

  
  
  
    
    <li class="md-nav__item md-nav__item--nested">
      
      
        <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_1" data-md-state="indeterminate" type="checkbox" id="__nav_1" checked>
      
      
      
      
        <label class="md-nav__link" for="__nav_1">
          Getting Started
          <span class="md-nav__icon md-icon"></span>
        </label>
      
      <nav class="md-nav" aria-label="Getting Started" data-md-level="1">
        <label class="md-nav__title" for="__nav_1">
          <span class="md-nav__icon md-icon"></span>
          Getting Started
        </label>
        <ul class="md-nav__list" data-md-scrollfix>
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="../../../.." class="md-nav__link">
        Introduction
      </a>
    </li>
  

            
          
            
              
  
  
  
    <li class="md-nav__item">
      <a href="../../../../ABOUT_CN/" class="md-nav__link">
        About
      </a>
    </li>
  

            
          
        </ul>
      </nav>
    </li>
  

    
  </ul>
</nav>
                  </div>
                </div>
              </div>
            
            
          
          <div class="md-content" data-md-component="content">
            <article class="md-content__inner md-typeset">
              
                


<h1 id="openvpn">异地组网之 OpenVPN 快速部署<a class="headerlink" href="#openvpn" title="Permanent link">&para;</a></h1>
<ul>
<li>
<p>相关文章1：<a href="https://blogs.wl4g.com/archives/3333">新一代高性能 Full Connects VPN 服务 WireGuard 快速部署</a></p>
</li>
<li>
<p>相关文章2：<a href="https://blogs.wl4g.com/archives/3707">异地组网之 IPSec 快速部署</a></p>
</li>
<li>
<p>相关文章3：<a href="https://blogs.wl4g.com/archives/3869">异地组网之 PPTP 快速部署 (ubuntu 20.04+pptpd+pptp-linux+win10)</a></p>
</li>
<li>
<p>原文参考1：<a href="https://github.com/hwdsl2/openvpn-install">https://github.com/hwdsl2/openvpn-install</a></p>
</li>
<li>
<p>原文参考2：<a href="https://community.openvpn.net/openvpn/wiki/OpenVPN3Linux">https://community.openvpn.net/openvpn/wiki/OpenVPN3Linux</a></p>
</li>
</ul>
<p>使用 Linux 脚本一键快速搭建自己的 OpenVPN 服务器。支持 Ubuntu, Debian, AlmaLinux, Rocky Linux, CentOS 和 Fedora 系统。</p>
<p>该脚本可让你在几分钟内建立自己的 VPN 服务器，即使你以前没有使用过 OpenVPN。OpenVPN 是一种开源、强大且高度灵活的 VPN 协议。</p>
<ul>
<li>特此申明：本教程仅推荐用于技术测试、个人学习使用，请勿用于非法等恶意用途，否则产生后果与本教程无关。</li>
</ul>
<h2 id="1-openvpn-server">1. OpenVPN Server 部署<a class="headerlink" href="#1-openvpn-server" title="Permanent link">&para;</a></h2>
<ul>
<li>1.1 一键交互式安装</li>
</ul>
<div class="highlight"><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1"></a><a href="#__codelineno-0-1"><span class="linenos" data-linenos=" 1 "></span></a>curl -L -o openvpn.sh https://get.vpnsetup.net/ovpn
<a id="__codelineno-0-2" name="__codelineno-0-2"></a><a href="#__codelineno-0-2"><span class="linenos" data-linenos=" 2 "></span></a><span class="c1"># 或墙内推荐:</span>
<a id="__codelineno-0-3" name="__codelineno-0-3"></a><a href="#__codelineno-0-3"><span class="linenos" data-linenos=" 3 "></span></a>curl -L -o openvpn.sh https://gitee.com/wl4g/blogs/raw/master/docs/articles/operation/openvpn-deploy/resources/openvpn.sh
<a id="__codelineno-0-4" name="__codelineno-0-4"></a><a href="#__codelineno-0-4"><span class="linenos" data-linenos=" 4 "></span></a>
<a id="__codelineno-0-5" name="__codelineno-0-5"></a><a href="#__codelineno-0-5"><span class="linenos" data-linenos=" 5 "></span></a><span class="c1"># 执行交互式安装</span>
<a id="__codelineno-0-6" name="__codelineno-0-6"></a><a href="#__codelineno-0-6"><span class="linenos" data-linenos=" 6 "></span></a>sudo chmod +x ./openvpn.sh
<a id="__codelineno-0-7" name="__codelineno-0-7"></a><a href="#__codelineno-0-7"><span class="linenos" data-linenos=" 7 "></span></a>sudo ./openvpn.sh
<a id="__codelineno-0-8" name="__codelineno-0-8"></a><a href="#__codelineno-0-8"><span class="linenos" data-linenos=" 8 "></span></a>
<a id="__codelineno-0-9" name="__codelineno-0-9"></a><a href="#__codelineno-0-9"><span class="linenos" data-linenos=" 9 "></span></a><span class="c1"># 查看 openvpn system service</span>
<a id="__codelineno-0-10" name="__codelineno-0-10"></a><a href="#__codelineno-0-10"><span class="linenos" data-linenos="10 "></span></a>sudo systemctl status openvpn-server@server
</code></pre></div>
<ul>
<li>1.2 管理客户端证书（同一脚本交互式）</li>
</ul>
<div class="highlight"><pre><span></span><code><a id="__codelineno-1-1" name="__codelineno-1-1"></a><a href="#__codelineno-1-1"><span class="linenos" data-linenos="1 "></span></a>sudo ./openvpn.sh
</code></pre></div>
<h2 id="2-openvpn-clients">2. OpenVPN Clients 安装<a class="headerlink" href="#2-openvpn-clients" title="Permanent link">&para;</a></h2>
<p>安装完成后，你可以再次运行脚本来管理用户或者卸载 OpenVPN。</p>
<p><a href="https://openvpn.net/vpn-client/">OpenVPN 客户端</a> 在 Windows, macOS, iOS, Android 和 Linux 上可用。macOS 用户也可以使用 Tunnelblick。要添加 VPN 连接，首先将生成的 .ovpn 文件安全地传送到你的设备，然后打开 OpenVPN 应用程序并导入 VPN 配置文件。</p>
<ul>
<li>官方文档：<a href="https://community.openvpn.net/openvpn/wiki/OpenVPN3Linux">community.openvpn.net/openvpn/wiki/OpenVPN3Linux</a></li>
</ul>
<h3 id="21-debian-or-ubuntu">2.1 Debian or Ubuntu<a class="headerlink" href="#21-debian-or-ubuntu" title="Permanent link">&para;</a></h3>
<ul>
<li>前置安装</li>
</ul>
<div class="highlight"><pre><span></span><code><a id="__codelineno-2-1" name="__codelineno-2-1"></a><a href="#__codelineno-2-1"><span class="linenos" data-linenos="1 "></span></a><span class="c1"># 首先确保 apt 支持 https</span>
<a id="__codelineno-2-2" name="__codelineno-2-2"></a><a href="#__codelineno-2-2"><span class="linenos" data-linenos="2 "></span></a>sudo apt install apt-transport-https
<a id="__codelineno-2-3" name="__codelineno-2-3"></a><a href="#__codelineno-2-3"><span class="linenos" data-linenos="3 "></span></a>
<a id="__codelineno-2-4" name="__codelineno-2-4"></a><a href="#__codelineno-2-4"><span class="linenos" data-linenos="4 "></span></a><span class="c1"># 下载 OpenVPN 3 Linux 软件包密钥</span>
<a id="__codelineno-2-5" name="__codelineno-2-5"></a><a href="#__codelineno-2-5"><span class="linenos" data-linenos="5 "></span></a>curl -fsSL https://swupdate.openvpn.net/repos/openvpn-repo-pkg-key.pub <span class="p">|</span> gpg --dearmor &gt; /etc/apt/trusted.gpg.d/openvpn-repo-pkg-keyring.gpg
<a id="__codelineno-2-6" name="__codelineno-2-6"></a><a href="#__codelineno-2-6"><span class="linenos" data-linenos="6 "></span></a>
<a id="__codelineno-2-7" name="__codelineno-2-7"></a><a href="#__codelineno-2-7"><span class="linenos" data-linenos="7 "></span></a><span class="c1"># 然后根据您的 Debian/Ubuntu 发行版，将 $DISTRO 替换为发行版名称。</span>
<a id="__codelineno-2-8" name="__codelineno-2-8"></a><a href="#__codelineno-2-8"><span class="linenos" data-linenos="8 "></span></a>curl -fsSL https://swupdate.openvpn.net/community/openvpn3/repos/openvpn3-<span class="nv">$DISTRO</span>.list &gt;/etc/apt/sources.list.d/openvpn3.list
<a id="__codelineno-2-9" name="__codelineno-2-9"></a><a href="#__codelineno-2-9"><span class="linenos" data-linenos="9 "></span></a>sudo apt update
</code></pre></div>
<ul>
<li>安装 openvpn</li>
</ul>
<div class="highlight"><pre><span></span><code><a id="__codelineno-3-1" name="__codelineno-3-1"></a><a href="#__codelineno-3-1"><span class="linenos" data-linenos="1 "></span></a>sudo apt install openvpn3
</code></pre></div>
<h3 id="22-fedora-red-hat-enterprise-linux-centos">2.2 Fedora, Red Hat Enterprise Linux, CentOS<a class="headerlink" href="#22-fedora-red-hat-enterprise-linux-centos" title="Permanent link">&para;</a></h3>
<ul>
<li>支持的发行版</li>
</ul>
<table>
<thead>
<tr>
<th>Distribution</th>
<th>Release versions</th>
<th>Architecture</th>
<th>DCO support</th>
</tr>
</thead>
<tbody>
<tr>
<td>Fedora</td>
<td>35, 36, Rawhide (*2)</td>
<td>aarch64, s390x, x86_64</td>
<td>yes (*1)</td>
</tr>
<tr>
<td>Red Hat Enterprise Linux / CentOS</td>
<td>7</td>
<td>x86_64</td>
<td>-</td>
</tr>
<tr>
<td>Red Hat Enterprise Linux</td>
<td>8</td>
<td>aarch64, x86_64</td>
<td>yes (*1)</td>
</tr>
<tr>
<td>Red Hat Enterprise Linux</td>
<td>9</td>
<td>aarch64, x86_64</td>
<td>yes (*1)</td>
</tr>
</tbody>
</table>
<ul>
<li>
<p>[*1] 请注意，DCO 支持目前被视为技术预览。</p>
</li>
<li>
<p>[*2] Fedora Rawhide 是一个移动的目标，在我们整理好构建环境所需的更改之前，会有一段时间没有可用的更新。</p>
</li>
</ul>
<p>如果您正在运行 Red Hat Enterprise Linux 或其克隆，您需要先安装 Fedora EPEL 存储库和 yum copr 模块。启用 Fedora EPEL 的说明可以在这里找到：​https://fedoraproject.org/wiki/EPEL。</p>
<div class="highlight"><pre><span></span><code><a id="__codelineno-4-1" name="__codelineno-4-1"></a><a href="#__codelineno-4-1"><span class="linenos" data-linenos="1 "></span></a><span class="c1"># Fedora 发行版通常预装了 yum/dnf copr 模块：https://docs.fedoraproject.org/en-US/epel/</span>
<a id="__codelineno-4-2" name="__codelineno-4-2"></a><a href="#__codelineno-4-2"><span class="linenos" data-linenos="2 "></span></a>sudo yum install yum-plugin-copr
<a id="__codelineno-4-3" name="__codelineno-4-3"></a><a href="#__codelineno-4-3"><span class="linenos" data-linenos="3 "></span></a>
<a id="__codelineno-4-4" name="__codelineno-4-4"></a><a href="#__codelineno-4-4"><span class="linenos" data-linenos="4 "></span></a><span class="c1"># 有了可用的 Copr 模块，是时候启用 OpenVPN 3 Copr 存储库了</span>
<a id="__codelineno-4-5" name="__codelineno-4-5"></a><a href="#__codelineno-4-5"><span class="linenos" data-linenos="5 "></span></a>sudo yum copr <span class="nb">enable</span> dsommers/openvpn3
<a id="__codelineno-4-6" name="__codelineno-4-6"></a><a href="#__codelineno-4-6"><span class="linenos" data-linenos="6 "></span></a>
<a id="__codelineno-4-7" name="__codelineno-4-7"></a><a href="#__codelineno-4-7"><span class="linenos" data-linenos="7 "></span></a><span class="c1"># 然后就可以安装 OpenVPN 3 Linux 客户端了</span>
<a id="__codelineno-4-8" name="__codelineno-4-8"></a><a href="#__codelineno-4-8"><span class="linenos" data-linenos="8 "></span></a>sudo yum install openvpn3-client
</code></pre></div>
<h3 id="23-openvpn2">2.3 使用 openvpn2 管理命令行<a class="headerlink" href="#23-openvpn2" title="Permanent link">&para;</a></h3>
<p>对于熟悉经典 OpenVPN 2.x 命令行的用户来说，openvpn3 会向前兼容。</p>
<ul>
<li>启动连接（临时）</li>
</ul>
<blockquote>
<p><font color=red>注：如果是在远程或云主机上启动 openvpn 连接，必须指定 route subnet，否则 openvpn 默认会添加 default 路由到 vpn_gateway，<a href="#2.5">参见&nbsp;#2.5&nbsp;自定义客户端路由
</a>，导致 SSH 连接中断。（万一出现这种情况就只能 VNC 了）</font></p>
</blockquote>
<div class="highlight"><pre><span></span><code><a id="__codelineno-5-1" name="__codelineno-5-1"></a><a href="#__codelineno-5-1"><span class="linenos" data-linenos="1 "></span></a><span class="c1"># 其中 myclient.ovpn 是在安装 OpenVPN server 时使用 openvpn.sh 工具生成.</span>
<a id="__codelineno-5-2" name="__codelineno-5-2"></a><a href="#__codelineno-5-2"><span class="linenos" data-linenos="2 "></span></a>sudo openvpn2 --config myclient.ovpn --verb <span class="m">6</span>
</code></pre></div>
<p>将 <code>myclient.ovpn</code> 替换为您要使用的 OpenVPN 配置文件。如果此配置包含该--daemon选项，VPN 会话将在后台启动，并再次向用户返回命令行。要进一步管理此 VPN 会话，openvpn3 session-manage必须使用命令行界面。如果没有<code>--daemon</code>控制台，将填充来自 VPN 会话的日志数据，并且可以通过终端中的简单 CTRL-C 断开会话。</p>
<ul>
<li>
<p>有关更多信息，请参阅 <code>openvpn2 --help</code> 或 <code>openvpn3 session-manage --help</code> 以及 <a href="https://github.com/OpenVPN/openvpn3-linux/blob/master/docs/man/openvpn2.1.rst">openvpn2</a> 和 <a href="https://github.com/OpenVPN/openvpn3-linux/blob/master/docs/man/openvpn3-session-manage.1.rst">openvpn3-session-manage</a> 手册。</p>
</li>
<li>
<p>连接验证</p>
</li>
</ul>
<div class="highlight"><pre><span></span><code><a id="__codelineno-6-1" name="__codelineno-6-1"></a><a href="#__codelineno-6-1"><span class="linenos" data-linenos=" 1 "></span></a><span class="c1"># 连接成功后即可看到 openvpn 创建的 tun0 网络设备</span>
<a id="__codelineno-6-2" name="__codelineno-6-2"></a><a href="#__codelineno-6-2"><span class="linenos" data-linenos=" 2 "></span></a>sudo ip a
<a id="__codelineno-6-3" name="__codelineno-6-3"></a><a href="#__codelineno-6-3"><span class="linenos" data-linenos=" 3 "></span></a>...
<a id="__codelineno-6-4" name="__codelineno-6-4"></a><a href="#__codelineno-6-4"><span class="linenos" data-linenos=" 4 "></span></a><span class="m">25</span>: tun0: &lt;POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP&gt; mtu <span class="m">1500</span> qdisc fq_codel state UNKNOWN group default qlen <span class="m">100</span>
<a id="__codelineno-6-5" name="__codelineno-6-5"></a><a href="#__codelineno-6-5"><span class="linenos" data-linenos=" 5 "></span></a>    link/none 
<a id="__codelineno-6-6" name="__codelineno-6-6"></a><a href="#__codelineno-6-6"><span class="linenos" data-linenos=" 6 "></span></a>    inet <span class="m">10</span>.8.0.2/24 brd <span class="m">10</span>.8.0.255 scope global tun0
<a id="__codelineno-6-7" name="__codelineno-6-7"></a><a href="#__codelineno-6-7"><span class="linenos" data-linenos=" 7 "></span></a>       valid_lft forever preferred_lft forever
<a id="__codelineno-6-8" name="__codelineno-6-8"></a><a href="#__codelineno-6-8"><span class="linenos" data-linenos=" 8 "></span></a>
<a id="__codelineno-6-9" name="__codelineno-6-9"></a><a href="#__codelineno-6-9"><span class="linenos" data-linenos=" 9 "></span></a><span class="c1"># 可看到 openvpn 创建了一条路由规则指向 tun0 设备（默认会将所有出口流量引到 10.8.0.1 上）</span>
<a id="__codelineno-6-10" name="__codelineno-6-10"></a><a href="#__codelineno-6-10"><span class="linenos" data-linenos="10 "></span></a>sudo ip r
<a id="__codelineno-6-11" name="__codelineno-6-11"></a><a href="#__codelineno-6-11"><span class="linenos" data-linenos="11 "></span></a><span class="m">0</span>.0.0.0/1 via <span class="m">10</span>.8.0.1 dev tun0
<a id="__codelineno-6-12" name="__codelineno-6-12"></a><a href="#__codelineno-6-12"><span class="linenos" data-linenos="12 "></span></a>default via <span class="m">10</span>.0.0.1 dev wlp2s0 proto dhcp metric <span class="m">600</span>
<a id="__codelineno-6-13" name="__codelineno-6-13"></a><a href="#__codelineno-6-13"><span class="linenos" data-linenos="13 "></span></a><span class="m">10</span>.0.0.0/24 dev wlp2s0 proto kernel scope link src <span class="m">10</span>.0.0.114 metric <span class="m">600</span>
<a id="__codelineno-6-14" name="__codelineno-6-14"></a><a href="#__codelineno-6-14"><span class="linenos" data-linenos="14 "></span></a><span class="m">10</span>.8.0.0/24 dev tun0 proto kernel scope link src <span class="m">10</span>.8.0.2
<a id="__codelineno-6-15" name="__codelineno-6-15"></a><a href="#__codelineno-6-15"><span class="linenos" data-linenos="15 "></span></a>...
<a id="__codelineno-6-16" name="__codelineno-6-16"></a><a href="#__codelineno-6-16"><span class="linenos" data-linenos="16 "></span></a>
<a id="__codelineno-6-17" name="__codelineno-6-17"></a><a href="#__codelineno-6-17"><span class="linenos" data-linenos="17 "></span></a><span class="c1"># 可以 ping 通虚拟局域网网关</span>
<a id="__codelineno-6-18" name="__codelineno-6-18"></a><a href="#__codelineno-6-18"><span class="linenos" data-linenos="18 "></span></a>ping <span class="m">10</span>.8.0.1
<a id="__codelineno-6-19" name="__codelineno-6-19"></a><a href="#__codelineno-6-19"><span class="linenos" data-linenos="19 "></span></a>PING <span class="m">10</span>.8.0.1 <span class="o">(</span><span class="m">10</span>.8.0.1<span class="o">)</span> <span class="m">56</span><span class="o">(</span><span class="m">84</span><span class="o">)</span> bytes of data.
<a id="__codelineno-6-20" name="__codelineno-6-20"></a><a href="#__codelineno-6-20"><span class="linenos" data-linenos="20 "></span></a><span class="m">64</span> bytes from <span class="m">10</span>.8.0.1: <span class="nv">icmp_seq</span><span class="o">=</span><span class="m">1</span> <span class="nv">ttl</span><span class="o">=</span><span class="m">64</span> <span class="nv">time</span><span class="o">=</span><span class="m">11</span>.2 ms
<a id="__codelineno-6-21" name="__codelineno-6-21"></a><a href="#__codelineno-6-21"><span class="linenos" data-linenos="21 "></span></a>...
</code></pre></div>
<h3 id="24-openvpn3">2.4 使用 openvpn3 管理命令行<a class="headerlink" href="#24-openvpn3" title="Permanent link">&para;</a></h3>
<p>对于更高级的用法，openvpn3 命令行提供了更多功能。OpenVPN 3 Linux 中的配置文件由配置管理器管理，然后通过会话管理器启动 VPN 会话。该openvpn3实用程序可以访问这些管理器服务提供的功能。</p>
<ul>
<li>启动连接（临时）</li>
</ul>
<blockquote>
<p><font color=red>注：如果是在远程或云主机上启动 openvpn 连接，必须指定 route subnet，否则 openvpn 默认会添加 default 路由到 vpn_gateway，<a href="#2.5">参见&nbsp;#2.5&nbsp;自定义客户端路由
</a>，导致 SSH 连接中断。（万一出现这种情况就只能 VNC 了）</font></p>
</blockquote>
<p>这意味着一旦尝试启动 VPN 会话，就会从配置管理中解析、加载和删除配置文件。在这种方法之后，没有配置文件可供重复使用。这是通过将配置文件直接提供给 openvpn3 session-start 命令来实现的。</p>
<div class="highlight"><pre><span></span><code><a id="__codelineno-7-1" name="__codelineno-7-1"></a><a href="#__codelineno-7-1"><span class="linenos" data-linenos="1 "></span></a>sudo openvpn3 session-start --config myclient.ovpn
</code></pre></div>
<ul>
<li>导入配置文件以重用并启动 VPN session</li>
</ul>
<p>使用这种方法，可以多次使用导入的配置文件，并且不需要访问配置文件本身来启动 VPN 隧道。默认情况下，导入的配置文件仅对导入配置文件的用户可用。但是 OpenVPN 3 Linux 还通过 <code>openvpn3 config-acl</code> 提供了访问控制列表功能，以授予系统上特定或所有用户的访问权限。</p>
<div class="highlight"><pre><span></span><code><a id="__codelineno-8-1" name="__codelineno-8-1"></a><a href="#__codelineno-8-1"><span class="linenos" data-linenos="1 "></span></a>sudo openvpn3 config-import --config myclient.ovpn
</code></pre></div>
<p>这将加载配置文件并将其仅存储在内存中。这意味着，如果系统重新启动，则不会保留配置文件。如果将 <code>--persistent</code> 参数添加到上面的命令行中，则配置文件将保存到磁盘中只有 openvpn 用户可以访问的目录中。每当启动配置管理器时，导入的配置文件 <code>--persistent</code> 也会自动加载。</p>
<ul>
<li>查看所有可用的配置文件</li>
</ul>
<div class="highlight"><pre><span></span><code><a id="__codelineno-9-1" name="__codelineno-9-1"></a><a href="#__codelineno-9-1"><span class="linenos" data-linenos="1 "></span></a>openvpn3 configs-list
</code></pre></div>
<p>配置文件通常包含能够连接到特定服务器的通用选项，而与设备本身无关。OpenVPN 3 Linux 还支持在配置文件上设置更多特定于主机的设置。这是通过 <code>openvpn3 config-manage</code> 接口处理的。如果使用参数导入配置文件，则此处的任何设置也将在引导期间保留 <code>--persistent</code>。</p>
<ul>
<li>管理正在运行的 VPN 会话</li>
</ul>
<p>一旦 VPN 会话开始，它应该会在​<code>openvpn3 sessions-list</code>中看到：</p>
<div class="highlight"><pre><span></span><code><a id="__codelineno-10-1" name="__codelineno-10-1"></a><a href="#__codelineno-10-1"><span class="linenos" data-linenos="1 "></span></a>openvpn3 sessions-list
</code></pre></div>
<ul>
<li>查询会话隧道实时统计数据</li>
</ul>
<div class="highlight"><pre><span></span><code><a id="__codelineno-11-1" name="__codelineno-11-1"></a><a href="#__codelineno-11-1"><span class="linenos" data-linenos="1 "></span></a>openvpn3 session-stats --config myclient.ovpn
</code></pre></div>
<ul>
<li>实时查看日志</li>
</ul>
<div class="highlight"><pre><span></span><code><a id="__codelineno-12-1" name="__codelineno-12-1"></a><a href="#__codelineno-12-1"><span class="linenos" data-linenos="1 "></span></a>openvpn3 log --config myclient.ovpn
</code></pre></div>
<ul>
<li>更多管理命令请参见：<a href="https://community.openvpn.net/openvpn/wiki/OpenVPN3Linux">https://community.openvpn.net/openvpn/wiki/OpenVPN3Linux</a></li>
</ul>
<h3 id="25">2.5 自定义客户端路由<a class="headerlink" href="#25" title="Permanent link">&para;</a></h3>
<p>如，通常在办公网中使用 openvpn 时，你可能只是需要访问某个特定的企业软件时才走 vpn，并不希望所有流量都走 vpn，这是很常规的需求，那么就可以通过自定义客户端路由实现。</p>
<div class="highlight"><pre><span></span><code><a id="__codelineno-13-1" name="__codelineno-13-1"></a><a href="#__codelineno-13-1"><span class="linenos" data-linenos=" 1 "></span></a><span class="c1"># 向客户端配置文件追加路由配置</span>
<a id="__codelineno-13-2" name="__codelineno-13-2"></a><a href="#__codelineno-13-2"><span class="linenos" data-linenos=" 2 "></span></a>sudo <span class="nb">echo</span> <span class="s2">&quot;</span>
<a id="__codelineno-13-3" name="__codelineno-13-3"></a><a href="#__codelineno-13-3"><span class="linenos" data-linenos=" 3 "></span></a><span class="s2">route-nopull # Get route from server after disable client connected.</span>
<a id="__codelineno-13-4" name="__codelineno-13-4"></a><a href="#__codelineno-13-4"><span class="linenos" data-linenos=" 4 "></span></a><span class="s2">max-routes 1000 # Max route entries limit, default 100</span>
<a id="__codelineno-13-5" name="__codelineno-13-5"></a><a href="#__codelineno-13-5"><span class="linenos" data-linenos=" 5 "></span></a><span class="s2">route 172.8.2.0 255.255.255.0 vpn_gateway # Need go to the output subnet of the ovpn gateway</span>
<a id="__codelineno-13-6" name="__codelineno-13-6"></a><a href="#__codelineno-13-6"><span class="linenos" data-linenos=" 6 "></span></a><span class="s2">route 192.168.8.0  255.255.255.0 net_gateway # Not go to the output subnet of the ovpn gateway</span>
<a id="__codelineno-13-7" name="__codelineno-13-7"></a><a href="#__codelineno-13-7"><span class="linenos" data-linenos=" 7 "></span></a><span class="s2">&quot;</span> &gt;&gt; myclient.ovpn
<a id="__codelineno-13-8" name="__codelineno-13-8"></a><a href="#__codelineno-13-8"><span class="linenos" data-linenos=" 8 "></span></a>
<a id="__codelineno-13-9" name="__codelineno-13-9"></a><a href="#__codelineno-13-9"><span class="linenos" data-linenos=" 9 "></span></a><span class="c1"># 然后重启 openvpn，如：</span>
<a id="__codelineno-13-10" name="__codelineno-13-10"></a><a href="#__codelineno-13-10"><span class="linenos" data-linenos="10 "></span></a>sudo ps -ef <span class="p">|</span> grep -v grep <span class="p">|</span> grep openvpn <span class="p">|</span> cut -c <span class="m">9</span>-16 <span class="p">|</span> xargs <span class="nb">kill</span> -s TERM
<a id="__codelineno-13-11" name="__codelineno-13-11"></a><a href="#__codelineno-13-11"><span class="linenos" data-linenos="11 "></span></a>nohup sudo openvpn --config /etc/openvpn/client/myclient.ovpn --verb <span class="m">6</span> &gt;&gt; /tmp/ovpn-client.out <span class="m">2</span>&gt;<span class="p">&amp;</span><span class="m">1</span> <span class="p">&amp;</span>
</code></pre></div>
<blockquote>
<p>以上路由表示，客户端仅访问 <code>172.8.2.0/24</code> 时才走 ovpn，而访问 <code>192.168.8.0/24</code> 时直接物理 Underlay 网络。</p>
</blockquote>
<h2 id="3-faq">3. FAQ<a class="headerlink" href="#3-faq" title="Permanent link">&para;</a></h2>
<h3 id="31-ubuntu-20x-openvpn-gnome-gui">3.1 关于在 Ubuntu 20.x 上使用默认集成的 OpenVPN gnome GUI 连接总是失败。<a class="headerlink" href="#31-ubuntu-20x-openvpn-gnome-gui" title="Permanent link">&para;</a></h3>
<ul>
<li>分析：这可能由于协议或认证机制兼容性导致，暂未做具体探究，但改用安装命令行客户端，<code>sudo openvpn --config your_openvpn_client.ovpn --verb 6</code> 即能连接成功。</li>
</ul>
<h3 id="32-openvpn">3.2 OpenVPN 集群部署<a class="headerlink" href="#32-openvpn" title="Permanent link">&para;</a></h3>
<ul>
<li>https://openvpn.net/access-server-manual/configuration-cluster/</li>
</ul>
<h3 id="33-openvpn-admin-ui">3.3 OpenVPN admin UI 部署<a class="headerlink" href="#33-openvpn-admin-ui" title="Permanent link">&para;</a></h3>
<blockquote>
<p>注：OpenVPN Access Server 简称 (openvpn-as) 组件是收费的，默认在官网注册会获得 2 个免费的连接。</p>
</blockquote>
<ul>
<li>https://openvpn.net/vpn-server-resources/command-line/</li>
</ul>
<h3 id="34-free">3.4 相关在线 FREE 地址<a class="headerlink" href="#34-free" title="Permanent link">&para;</a></h3>
<ul>
<li>
<p><a href="https://www.vpngate.net/cn/">https://www.vpngate.net/cn/</a></p>
</li>
<li>
<p><a href="https://www.freeopenvpn.org/premium.php?cntid=UK&amp;lang=en">https://www.freeopenvpn.org/premium.php?cntid=UK&amp;lang=en</a></p>
</li>
<li>
<p><a href="https://openvpn.net/access-server-manual/configuration-cluster/">https://openvpn.net/access-server-manual/configuration-cluster/</a></p>
</li>
</ul>
<h3 id="35-cdh">3.5 实坑！在企业级环境中，可能需要在办公内网访问远程 CDH 集群内网中的服务，如何解决?<a class="headerlink" href="#35-cdh" title="Permanent link">&para;</a></h3>
<ul>
<li>
<p>分析：此需求的特殊性在于，由于如 NameNode / DataNode / Kafka 等组件各节点的通信地址是配置死的（如 nn1 的 hdfs rpc 地址是 172.8.2.100:8020），如下以执行 <code>hdfs dfs -ls /</code> 为例的网络包途径（通过wireshark分析）：TODO</p>
</li>
<li>
<p>思路：本地在进入 tun0 之前 dnat，远程A在到 NameNode 进程之前 snat</p>
</li>
<li>
<p>解决：通过增加 iptables 规则，将出站 172.8.2.0/24 的流量转向 10.8.0.0/24 (ovpn tun0设备)</p>
</li>
<li>
<p><font color=red><b>坑1</b>：亲测还发现，openvpn client 会修改 <code>net.ipv6.bindv6only=1</code>，这样会导致与 CDH HBase 启动冲突，因为它要求禁用，因此需手动改回来：<code>sysctl -w net.ipv6.bindv6only=0</code></font></p>
</li>
<li>
<p><font color=red><b>坑2</b>：亲测还发现，当与 kubenetes+calico 一起部署时，由于 openvpn client 启动会创建 tun0 设备，这也会与 calico-node 冲突，因为它会读到 tun0 的 ip，暂时只能先手动停止 openvpn 并删除 <code>ip link del tun0</code>，后续可以尝试让 calico 过滤掉 tun0 或者自定义 openvpn 路由看是否可行？</font></p>
</li>
</ul>

              
            </article>
          </div>
        </div>
        
      </main>
      
        <footer class="md-footer">
  
  <div class="md-footer-meta md-typeset">
    <div class="md-footer-meta__inner md-grid">
      <div class="md-copyright">
  
  
    Made with
    <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
      Material for MkDocs
    </a>
  
</div>
      
    </div>
  </div>
</footer>
      
    </div>
    <div class="md-dialog" data-md-component="dialog">
      <div class="md-dialog__inner md-typeset"></div>
    </div>
    <script id="__config" type="application/json">{"base": "../../../..", "features": ["search.suggest", "search.highlight", "navigation.tabs", "navigation.expand", "toc.follow", "toc.integrate"], "search": "../../../../assets/javascripts/workers/search.5e67fbfe.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version.title": "Select version"}, "version": {"default": "latest", "provider": "mike"}}</script>
    
    
      <script src="../../../../assets/javascripts/bundle.c44cc438.min.js"></script>
      
        <script src="../../../../static/js/util.js"></script>
      
    
  </body>
</html>